package util;

import jcumf.umf_javacall;

public class RfidTool {
	private static umf_javacall rd;// 通用接口
	private static int lDevice;// 设备描述符
	private static short status;// 状态
	private static short findCardMode;// 如果是多卡模式，则设置为1;如果是单卡模式，则设置为0
	private static char[] pSnrM1s;// M1卡序列号字符串
	private static char[] pSnrM1;// M1卡序列号字符串
	private static char[] pSBuffer;// 扇区的密码
	private static short keyMode;// 装密码模式 0是A 4是B
	private static int[] pval = new int[1];// 放值的容器

	private static RfidTool fidTool = null;

	private RfidTool() {}
	/**
	 * 单例模式获取
	 * @author 训码科技 石嘉懿
	 * @date 2021年1月18日
	 * @return RfidTool
	 * @throws
	 */
	public static RfidTool getInstance() {
		if (fidTool == null) {
			fidTool = new RfidTool();
		}
		return fidTool;
	}

	private void myinit() {
		lDevice = 0;
		findCardMode = 1;
		pSnrM1s = new char[8];
		pSBuffer = new char[16];
		pSnrM1 = new char[8];
		rd = new umf_javacall();
		keyMode = 0;
		// 后期16位密码存入数据库
		pSBuffer[0] = 0xFF;
		pSBuffer[1] = 0xFF;
		pSBuffer[2] = 0xFF;
		pSBuffer[3] = 0xFF;
		pSBuffer[4] = 0xFF;
		pSBuffer[5] = 0xFF;
	}


	/**
	 * 调用驱动程序连接设备
	 * @author 训码科技 石嘉懿
	 * @date 2021年1月18日
	 * @return String 成功或失败信息
	 * @throws
	 */
	@SuppressWarnings("static-access")
	public String getdeviceInti() {
		if (deviceInti()) {
			rd.fw_exit(lDevice);// 退出连接
			return "设备连接成功";
		} else {
			return "设备连接失败。";
		}
	}

	@SuppressWarnings("static-access")
	private boolean deviceInti() {
		lDevice = rd.fw_init(100, 115200);// 初始化通信口 100表示使用USB通信口
		rd.fw_beep(lDevice, (short) 100);// 蜂鸣
		// 115200是波特率(用USB通信口时无效)
		if (lDevice <= 0) {
			return false;
		}
		return true;
	}

	/**
	 * @author 石嘉懿
	 * @value 密码和卡的检测
	 * @param { tsector 扇区 }
	 * @return 失败信息
	 *
	 */
	@SuppressWarnings("static-access")
	private String connection(short tsector) {
		myinit();
		boolean dei = deviceInti();
		if (!dei) {
			return "设备初始化失败";
		}
		status = rd.fw_beep(lDevice, (short) 10);
		if (status != 0) {
			return "蜂鸣失败！错误码"+status;
		}
		status = rd.fw_card_hex(lDevice, (short) findCardMode, pSnrM1);
		if (status != 0) {
			return "没有找到卡！错误码" + status;
		}

		status = rd.fw_authentication(lDevice, (short) keyMode, (short) tsector);
		if (status != 0) {
			rd.fw_exit(lDevice);// 退出连接
			return "核对密码函数！错误码" + status;
		}

		return "成功";
	}

	/**
	 * @author 石嘉懿
	 * @value 直接覆盖值
	 * @param tblk    块，一个扇区4个块，请注意扇区和块是否匹配
	 * @param num     初始化的值
	 * @param tsector 扇区
	 * @return 失败信息
	 *
	 */
	@SuppressWarnings("static-access")
	public String coverValue(short tsector, short tblk, short num) {
		String info = connection(tsector);
		if (info.equals("成功")) {
			status = rd.fw_initval(lDevice, tblk, num);
			if (status != 0) {
				rd.fw_exit(lDevice);// 退出连接
				return "初始化块值失败,检查扇区和块是否匹配。错误码"+status;
			}
			rd.fw_exit(lDevice);// 退出连接
			// TODO 应该判断数据库是否有这张卡，如果有就不能发卡
			return "成功！";
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return info;
		}

	}

	/**
	 * @author 石嘉懿
	 * @value 值的增加
	 * @param tblk    块，一个扇区4个块，请注意扇区和块是否匹配
	 * @param num     增加的值
	 * @param tsector 扇区
	 * @return 失败信息
	 *
	 */
	@SuppressWarnings("static-access")
	public String plus(short tsector, short tblk, short num) {
		String info = connection(tsector);
		if (info.equals("成功")) {
			status = rd.fw_increment(lDevice, (short) tblk, (short) num);
			if (status != 0) {
				rd.fw_exit(lDevice);// 退出连接
				return "失败！错误码"+status;
			}
			rd.fw_transfer(lDevice, (short) tblk);// 装配，刷入
			rd.fw_halt(lDevice);// 进入HALT 模式，必须把卡移开才能继续操作
			rd.fw_exit(lDevice);// 退出连接
			return "值增加成功：" + num;
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return info;
		}
	}

	/**
	 * @author 石嘉懿
	 * @value 值的减少
	 * @param tblk    块，一个扇区4个块，请注意扇区和块是否匹配
	 * @param num     减少的值
	 * @param tsector 扇区
	 * @return 失败信息
	 *
	 */
	@SuppressWarnings("static-access")
	public String less(short tsector, short tblk, short num) {
		String info = connection(tsector);
		if (info.equals("成功")) {
			status = rd.fw_decrement(lDevice, (short) tblk, (short) num);
			if (status != 0) {
				rd.fw_exit(lDevice);// 退出连接
				return "失败！错误码"+status;
			}
			rd.fw_transfer(lDevice, (short) tblk);// make valid 刷进去
			rd.fw_exit(lDevice);// 退出连接
			return "减少成功：" + num;
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return info;
		}
	}

	/**
	 * @author 石嘉懿
	 * @value 查询方法
	 * @param tblk    块，一个扇区4个块，请注意扇区和块是否匹配
	 * @param tsector 扇区
	 * @param info    传递成功或错误信息
	 * @return 查询出的int数组 返回为空查询失败
	 *
	 */
	@SuppressWarnings("static-access")
	public int[] show(short tsector, short tblk) {
		String myinfo = connection(tsector);
		if (myinfo.equals("成功")) {
			status = rd.fw_readval(lDevice, (short) tblk, pval);
			if (status != 0) {
				rd.fw_exit(lDevice);// 退出连接
				return null;
			}
			rd.fw_exit(lDevice);// 退出连接
			return pval;
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return null;
		}
	}

	/**
	 * @author 石嘉懿
	 * @value 查询卡唯一Id
	 * @return 查询出的int数组 返回为空查询失败
	 *
	 */
	@SuppressWarnings("static-access")
	public String showCardId() {
		String myinfo = connection((short) 0);
		if (myinfo.equals("成功")) {
			status = rd.fw_readval(lDevice, (short) 0, pval);
			rd.fw_exit(lDevice);// 退出连接
			if (status != 0) {
				return "失败！错误码"+status;
			}
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < pval.length; i++) {
				sb.append(pval[i]);
			}
			return sb.toString();
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return myinfo;
		}
	}

	/**
	 * @author 石嘉懿 未经老师运行不可调用此方法
	 * @value 扇区修改密码方法
	 * @param tsector       扇区
	 * @param changekeyMode 0代表修改A密码。4代表修改B密码
	 * @param mybuffer      一个密码数组如 使用16位 pSBuffer[0] = 0xFF; pSBuffer[1] = 0xFF;
	 *                      pSBuffer[2] = 0xFF; pSBuffer[3] = 0xFF; pSBuffer[4] =
	 *                      0xFF; pSBuffer[5] = 0xFF;
	 * @return 返回错误/成功信息
	 *
	 */
	@SuppressWarnings("static-access")
	private String changePassword(short tsector, short changekeyMode, char[] mybuffer) {
		boolean dei = deviceInti();
		if (dei) {
			status = rd.fw_load_key(lDevice, (short) changekeyMode, (short) tsector, mybuffer);
			System.out.println(lDevice);
			if (status != 0) {
				rd.fw_exit(lDevice);// 退出连接
				rd.fw_halt(lDevice);
				return "扇区密码修改失败";
			} else {
				rd.fw_exit(lDevice);// 退出连接
				return "成功";
			}
		} else {
			rd.fw_exit(lDevice);// 退出连接
			return "设备初始化失败";
		}
	}

}
